package muxwstemplate

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"time"

	"github.com/gorilla/mux"
)

type BaseController struct {
}

func (b *BaseController) UpgradeToWebSocket(w http.ResponseWriter, r *http.Request, groupName string, whenMsgArrived func([]byte) []byte) {
	UpgradeToWebSocket(w, r, groupName, whenMsgArrived)
}

func (b *BaseController) GetBodyParam(r *http.Request, formatObj interface{}) error {

	body, err := io.ReadAll(r.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(body, formatObj)
	if err != nil {
		return err
	}

	return nil
}

func (b *BaseController) GetQueryParam(r *http.Request, paramName string) (string, error) {

	paramsValue := r.URL.Query().Get(paramName)

	if paramsValue == "" {
		return "", fmt.Errorf("cannot find param with name %s", paramName)
	}

	return paramsValue, nil
}

func (b *BaseController) GetQueryParamMustInt(r *http.Request, paramName string) (int, error) {

	paramsValue, err := b.GetQueryParam(r, paramName)

	if paramsValue == "" {
		return 0, err
	}

	return strconv.Atoi(paramsValue)
}

func (b *BaseController) GetQueryParamMustBool(r *http.Request, paramName string) (bool, error) {

	paramsValue, err := b.GetQueryParam(r, paramName)

	if paramsValue == "" {
		return false, err
	}

	return strconv.ParseBool(paramsValue)
}

func (b *BaseController) GetQueryParamMustFloat(r *http.Request, paramName string) (float64, error) {

	paramsValue, err := b.GetQueryParam(r, paramName)

	if paramsValue == "" {
		return 0, err
	}

	return strconv.ParseFloat(paramsValue, 64)
}

func (b *BaseController) GetQueryParamOrDefault(r *http.Request, paramName string, defaultValue string) string {

	paramValue, err := b.GetQueryParam(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetQueryParamMustIntOrDefault(r *http.Request, paramName string, defaultValue int) int {

	paramValue, err := b.GetQueryParamMustInt(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetQueryParamMustBoolOrDefault(r *http.Request, paramName string, defaultValue bool) bool {

	paramValue, err := b.GetQueryParamMustBool(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetQueryParamMustFloatOrDefault(r *http.Request, paramName string, defaultValue float64) float64 {

	paramValue, err := b.GetQueryParamMustFloat(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetPathParam(r *http.Request, paramName string) (string, error) {

	vars := mux.Vars(r)
	paramsValue, err := vars[paramName]

	if err {
		return paramsValue, nil
	} else {
		return "", fmt.Errorf("cannot find param with name %s", paramName)
	}
}

func (b *BaseController) GetPathParamMustInt(r *http.Request, paramName string) (int, error) {

	paramsValue, err := b.GetPathParam(r, paramName)

	if paramsValue == "" {
		return 0, err
	}

	return strconv.Atoi(paramsValue)
}

func (b *BaseController) GetPathParamMustBool(r *http.Request, paramName string) (bool, error) {

	paramsValue, err := b.GetPathParam(r, paramName)

	if paramsValue == "" {
		return false, err
	}

	return strconv.ParseBool(paramsValue)
}

func (b *BaseController) GetPathParamMustFloat(r *http.Request, paramName string) (float64, error) {

	paramsValue, err := b.GetPathParam(r, paramName)

	if paramsValue == "" {
		return 0, err
	}

	return strconv.ParseFloat(paramsValue, 64)
}

func (b *BaseController) GetPathParamOrDefault(r *http.Request, paramName string, defaultValue string) string {

	paramValue, err := b.GetPathParam(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetPathParamMustIntOrDefault(r *http.Request, paramName string, defaultValue int) int {

	paramValue, err := b.GetPathParamMustInt(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetPathParamMustBoolOrDefault(r *http.Request, paramName string, defaultValue bool) bool {

	paramValue, err := b.GetPathParamMustBool(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) GetPathParamMustFloatOrDefault(r *http.Request, paramName string, defaultValue float64) float64 {

	paramValue, err := b.GetPathParamMustFloat(r, paramName)

	if err != nil {
		return defaultValue
	}

	return paramValue
}

func (b *BaseController) Response(w http.ResponseWriter, resultCode string, resultMsg string, data interface{}) {

	result := ResponseTemplate{
		ResultCode: resultCode,
		ResultMsg:  resultMsg,
		Data:       data,
		SysTime:    time.Now().Format("2006-01-02 15:04:05"),
	}

	marshal, _ := json.Marshal(result)
	w.Write(marshal)
}

func (b *BaseController) Success(w http.ResponseWriter, data interface{}) {

	result := ResponseTemplate{
		ResultCode: ResultStatusSuccess,
		ResultMsg:  "success",
		Data:       data,
		SysTime:    time.Now().Format("2006-01-02 15:04:05"),
	}

	marshal, _ := json.Marshal(result)

	w.Write(marshal)
}

func (b *BaseController) Fail(w http.ResponseWriter, err error) {

	result := ResponseTemplate{
		ResultCode: ResultStatusFail,
		ResultMsg:  "fail",
		Data:       err.Error(),
		SysTime:    time.Now().Format("2006-01-02 15:04:05"),
	}

	marshal, _ := json.Marshal(result)

	w.Write(marshal)
}

const (
	ResultStatusSuccess = "1"
	ResultStatusFail    = "0"
)

type ResponseTemplate struct {
	ResultCode string      `json:"resultCode"`
	ResultMsg  string      `json:"resultMsg"`
	Data       interface{} `json:"data"`
	SysTime    string      `json:"sysTime"`
}
